package com.kelvin.backend.okhttp.service;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.ContentType;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;

/**
 * <p>Title: OkHttpService</p>
 * <p>Description: </p>
 *
 * @author Kelvin.Chen
 * @datetime 2021/7/12 11:01
 */
@Service("okhttpService")
public class OkHttpService implements IOkHttpService {

    private static final Logger log = LoggerFactory.getLogger(OkHttpService.class);

    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final MediaType XML = MediaType.parse("application/xml; charset=utf-8");
    private static final MediaType FORM_DATA = MediaType.parse("multipart/form-data");

    @Autowired
    private OkHttpClient okHttpClient;

    @Override
    public String doGet(String url, Map<String, String> params, Map<String, String> headers) {
        log.info("[OkHttpService] -> get请求方式");
        // 组装入参
        StringBuilder paramsBuilder = new StringBuilder(url);
        if (!ObjectUtils.isEmpty(params)) {
            boolean firstFlag = true;
            for (Map.Entry<String, String> param : params.entrySet()) {
                if (firstFlag) {
                    paramsBuilder.append("?").append(param.getKey()).append("=").append(param.getValue());
                    firstFlag = false;
                } else {
                    paramsBuilder.append("&").append(param.getKey()).append("=").append(param.getValue());
                }
            }
        }

        // 组装Header
        Request.Builder builder = new Request.Builder();
        if (!ObjectUtils.isEmpty(headers)) {
            for (Map.Entry<String, String> header : headers.entrySet()) {
                builder.addHeader(header.getKey(), header.getValue());
            }
        }

        Request request = builder.url(paramsBuilder.toString()).build();

        return call(request);
    }

    @Override
    public String doPostForm(String url, Map<String, String> params) {
        log.info("[OkHttpService] -> post请求方式， form表单形式");
        FormBody.Builder builder = new FormBody.Builder();
        if (!ObjectUtil.isEmpty(params)) {
            for (Map.Entry<String, String> param : params.entrySet()) {
                builder.add(param.getKey(), param.getValue());
            }
        }
        Request request = new Request.Builder().url(url)
                .post(builder.build()).build();

        return call(request);
    }

    @Override
    public String doPostJson(String url, String json) {
        log.info("[OkHttpService] -> post请求方式， json形式");
        return call(url, json, JSON);
    }

    @Override
    public String doPostXml(String url, String xml) {
        log.info("[OkHttpService] -> post请求方式， xml形式");
        return call(url, xml, XML);
    }

    @Override
    public String update(String url, String filePath, String fileName) {
        log.info("[OkHttpService] -> 文件上传");
        if (ObjectUtil.isEmpty(fileName)) {
            fileName = FileUtil.getName(filePath);
        }
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", fileName,
                        RequestBody.create(new File(filePath), FORM_DATA))
                .build();

        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();

        return call(request);
    }

    /**
     * post方式调用，指定content-type
     *
     * @param url
     * @param data
     * @param contentType
     * @return
     */
    private String call(String url, String data, MediaType contentType) {
        RequestBody requestBody = RequestBody.create(data, contentType);
        Request request = new Request.Builder().url(url).post(requestBody).build();

        return call(request);
    }

    /**
     * 调用
     *
     * @param request
     * @return
     */
    private String call(Request request) {
        Response response = null;

        try {
            response = okHttpClient.newCall(request).execute();
            if (response.isSuccessful()) {
                return Objects.requireNonNull(response.body()).string();
            }
        } catch (IOException e) {
            log.error("[OkhttpService] 出现异常 -> ", e);
        } finally {
            IoUtil.close(response);
        }

        return "";
    }
}
